<template>
  <div class="page-container">
    <slot name="title"></slot>
    <div class="page-container-search">
      <div class="b2nd" v-if="addBtnInfo.show">
        <a-button type="primary" @click="showModal(addBtnInfo, {})"
          ><i v-if="addBtnInfo.icon" :class="addBtnInfo.icon"></i
          >{{ addBtnInfo.label || "新增" }}</a-button
        >
      </div>
      <div class="search-row flex items-center" v-if="pageData.form">
        <FormSearch
          :id="id"
          :data="pageData.form.data"
          :btns="pageData.form.btns"
          :showBtns="pageData.form.showBtns"
          @search="search"
          @btnCK="btnCK"
        ></FormSearch>
      </div>
    </div>

    <slot></slot>
    <CommonTable
      v-if="pageData.table"
      :id="id"
      :data="pageData.table.data"
      :columns="pageData.table.columns"
      ref="tableRef"
      v-bind="{ ...pageData.table }"
      @operateChange="operateChange"
      @selectionChange="selectionChange"
      @queryDataChange="queryDataChange"
    >
      <template
        v-for="(item, i) in pageData.table.columns"
        :key="i"
        #[item.slotName]="data"
      >
        <div :class="item.slotName + '-' + id">
          <slot :name="item.slotName" :record="data.record"></slot>
        </div>
      </template>
    </CommonTable>
    <CommenCard
      v-if="pageData.card"
      :id="id"
      :data="pageData.card.data"
      :columns="pageData.card.columns"
      ref="tableRef"
      v-bind="{ ...pageData.card }"
      @operateChange="operateChange"
      @queryDataChange="queryDataChange"
    >
      <template #card="data">
        <slot name="card" :list="data.list"></slot>
      </template>
    </CommenCard>
    <CommonModal
      v-if="pageData.modal"
      ref="modalRef"
      :data="pageData.modal.data"
      :layout="pageData.modal.layout"
      :title="pageData.modal.title"
      v-bind="{ ...pageData.modal }"
      @change="changeModal"
      @confirm="handleModalOk"
      @close="closeModal"
    >
      <template v-if="pageData.modal.slotName" #[pageData.modal.slotName]>
        <slot :name="pageData.modal.slotName" :row="viewInfo"></slot>
      </template>
      <template v-for="(md, i) in pageData.modal.data" :key="i" #[md.slotName]>
        <slot v-if="md.slotName" :name="md.slotName"></slot>
      </template>
    </CommonModal>
  </div>
</template>
<script setup>
import Tool from "@/utils/tool";
import store from "@/store";
import { downloadXlsx } from "@/utils/json2xlsx";
import { Modal, message } from "ant-design-vue";
import { defineExpose } from "vue";

const slots = useSlots();
const emit = defineEmits();
const id = ref(Tool.uuid());

const tableRef = ref(null);
const modalRef = ref(null);
const modalValue = ref({});
const viewInfo = ref({});

const props = defineProps({
  pageData: {
    type: Object,
    default: () => {
      return {};
    },
  },
});

const addBtnInfo = ref({
  key: "create",
  label: "新增",
  type: "primary",
  icon: "plus",
  show: true,
});

if (!props.pageData.addBtn) {
  addBtnInfo.value.show = false;
} else if (props.pageData.addBtn instanceof Function) {
  addBtnInfo.value.method = props.pageData.addBtn;
} else if (props.pageData.addBtn instanceof Object) {
  addBtnInfo.value = { ...props.pageData.addBtn, key: "create", show: true };
}

console.log(props.pageData, "addBtnInfo");

const queryDataChange = (val) => {
  emit("queryDataChange", val);
};

/**
 * 触发表格查询操作。
 *
 * 该函数用于触发表格的查询操作。它通过引用tableRef来调用queryList方法，
 * 从而更新或刷新表格的数据。此函数无参数，也不返回任何值。
 *
 * @param {Object} obj - 传递给queryList方法的参数对象。这里的参数对象为空，
 *                       因为函数实现中并未使用任何特定参数来调用queryList。
 */
const search = (obj) => {
  tableRef.value?.fetchData();
};
const btnCK = (obj) => {
  if (obj.btn.key === "exportXlsx") {
    const data = tableRef.value?.getData();
    const nm = Tool.uuid();
    downloadXlsx(
      id.value,
      data,
      props.pageData.table.columns,
      obj.btn.exportName || nm
    );
  }
};

const titleMap = {
  edit: "编辑",
  create: "新增",
  delete: "删除",
  view: "查看",
};

const changeModal = (val, val2) => {
  const v = Object.assign({}, val);
  Object.keys(v).forEach((key) => {
    const a = props.pageData.modal.data.filter((a) => a.field === key);

    if (a && a.length) {
      if (a[0].arr2str && v[key]) {
        if (a[0].type === "Upload") {
          v[key] = v[key];
        } else {
          v[key] = v[key] || currentRow.value[k];
        }
      }
      if (a[0].arr2obj && v[key]) {
        a[0].arr2obj.forEach((k, i) => {
          v[k] = v[key] ? v[key][i] : currentRow.value[k];
        });
      }
    }
  });
  modalValue.value = v;
  emit("changeModel", modalValue.value);
};

const isModify = ref(false);
const currentRow = ref({});
const currentBtn = ref({});

const rest = () => {
  modalRef.value?.close();
  tableRef.value?.fetchData();
};

/**
 * 弹窗信息初始化获取数据
 */
const getPreset = async (btn) => {
  const { code, data } = await btn.preset();
  if (code === rescf.codeVal) {
    modalRef.value?.setForm(data);
  }
};

/**
 * 显示模态框
 * @param {Object} obj - 模态框配置对象
 * @param {Object} row - 行数据
 * 设置模态框的标题并显示模态框
 */
const showModal = async (obj, row) => {
  modalRef.value?.setTitle(
    obj.title
      ? obj.title
      : props.pageData.modal.title instanceof Object
      ? props.pageData.modal.title.text
      : titleMap[obj.key] + props.pageData.modal.title
  );
  modalRef.value?.showModal();
  currentRow.value = row;
  currentBtn.value = obj;
  isModify.value = obj.key === "edit";
  console.log(obj, "===obj====");
  if (obj.beforeCreate) {
    const { code, data } = await obj.beforeCreate(row);
    if (code === rescf.codeVal) {
      modalRef.value?.setForm(data);
    }
  }
  if (obj.key === "edit") {
    nextTick(() => {
      const v = { ...row };
      Object.keys(v).forEach((key) => {
        const a = props.pageData.modal.data.filter((a) => a.field === key);
        if (a && a.length && a[0].arr2str && v[key]) {
          v[key] = v[key].split(",");
        }
      });
      modalRef.value?.setForm(v);
    });
  } else if (obj.key === "view") {
    handelDetail(obj, row);
  }
};

/**
 * 处理详情操作
 * @param {Object} obj - 操作配置对象
 * @param {Object} row - 行数据
 * 调用删除方法，并根据返回结果提示用户
 */

const handelDetail = async (obj, row) => {
  if (obj.method) {
    const o = {};
    o[obj.argKey || "id"] = row[obj.argValue || "id"];
    const { code, data, msg } = await obj.method(o);
    if (code === rescf.codeVal) {
      viewInfo.value = data;
    } else {
      message.error(msg);
    }
  }
};

/**
 * 处理删除操作
 * @param {Object} obj - 删除操作配置对象
 * @param {Object} row - 行数据
 * 调用删除方法，并根据返回结果提示用户
 */
const handleDelete = async (obj, row) => {
  if (obj.method) {
    const o = {};
    o[obj.argKey || "id"] = row[obj.argValue || obj.argKey || "id"];
    console.log(o, obj, "o0000");
    const { code, msg } = await obj.method(o);
    if (code === rescf.codeVal) {
      rest();
      message.info("删除成功！");
    } else {
      message.error(msg);
    }
  }
};

/**
 * 异步处理编辑操作。
 * 当前按钮具有method属性时，调用该方法，通过传递特定的参数来执行编辑操作。
 * 参数o包含当前行的特定id或其他指定的参数，以及模态框中的值。
 * 如果操作成功，刷新表格数据并显示成功消息；如果失败，则显示错误消息。
 */
const handleEdit = async () => {
  if (currentBtn.value.method) {
    const o = {};
    o[currentBtn.value.argKey || "id"] =
      currentRow.value[
        currentBtn.value.argValue || currentBtn.value.argKey || "id"
      ];

    if (currentBtn.value.params) {
      currentBtn.value.params.forEach((key) => {
        o[key] = currentRow.value[key];
        if (key instanceof String) {
        } else if (key instanceof Object) {
          o[Object.keys(key)[0]] = Object.values(key)[0];
        }
      });
    }
    const { code, msg, data } = await currentBtn.value.method(
      Object.assign({}, o, modalValue.value)
    );
    if (code === rescf.codeVal) {
      rest();
      if (currentBtn.value.success)
        currentBtn.value.success({ ...modalValue.value }, data);
      message.info(currentBtn.value.label + "成功！");
    } else {
      message.error(msg);
    }
  }
};

/**
 * 异步处理创建操作。
 * 当前按钮具有method属性时，调用该方法，通过传递模态框中的值来执行创建操作。
 * 如果操作成功，刷新表格数据并显示成功消息；如果失败，则显示错误消息。
 */
const handleCreate = async () => {
  if (currentBtn.value.method) {
    console.log("currentBtn.value", modalValue.value);
    const { code, msg, data } = await currentBtn.value.method(
      Object.assign({}, modalValue.value)
    );
    if (code === rescf.codeVal) {
      rest();
      if (currentBtn.value.success)
        currentBtn.value.success({ ...modalValue.value }, data);
      message.info(currentBtn.value.label + "成功！");
    } else {
      message.error(msg);
    }
  }
};

/**
 * 处理模态框的确定按钮点击事件。
 * 根据isModify.value的值决定执行编辑（handleEdit）还是创建（handleCreate）操作。
 * 该函数封装了对编辑和创建操作的调用逻辑，以复用模态框确认操作的处理流程。
 */
const handleModalOk = () => {
  if (isModify.value) {
    handleEdit();
  } else {
    handleCreate();
  }
};

/**
 * 显示删除确认框
 * @param {Object} obj - 确认框配置对象
 * @param {Object} row - 行数据
 * 使用模态框确认删除操作，用户确认后调用handleDelete处理删除
 */
const showDelete = (obj, row) => {
  Modal.confirm({
    title: obj.title || "温馨提示",
    content: obj.content,
    onOk() {
      handleDelete(obj, row);
    },
    onCancel() {},
  });
};

/**
 * 表格选中变化事件
 *
 */
const selectionChange = (val, row) => {
  emit("operateChange", val, row);
};

/**
 * 处理操作变化事件并触发自定义事件。
 *
 * 此函数用于处理表格行的操作变化，并通过emit函数触发一个名为"operateChange"的自定义事件。
 * 事件携带两个参数：操作类型(type)和相关行数据(row)。这个函数使得外部可以监听并响应表格内部的操作变化。
 *
 * @param {string} type - 操作类型。表示对行数据进行的操作，如"编辑"、"删除"等。
 * @param {Object} row - 行数据对象。包含被操作的行的所有数据。
 */
const operateChange = (obj, row) => {
  emit("operateChange", obj, row);
  switch (obj.key) {
    case "create":
    case "edit":
    case "view":
      showModal(obj, row);
      break;
    case "delete":
      showDelete(obj, row);
      break;
    default:
      break;
  }
};

const closeModal = () => {
  emit("closeModal");
};

const queryList = () => {
  tableRef.value?.fetchData();
};

defineExpose({
  queryList,
});
</script>
<style lang="scss" scoped>
.search-row {
  margin: 10px 0;
  flex: 1;
}
.page-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: var(--form-search-bg-color);
  .page-container-search {
    width: 100%;
    display: flex;
    align-items: center;
  }
  .b2nd {
    button {
      margin: 25px 0 25px 30px;
      i {
        margin-right: 5px;
        font-size: 13px;
      }
    }
  }
}
</style>
